吾日三省吾身,為人謀而不忠乎,與朋友交而不信乎,傳不習乎?
這一回是有點偷懶了,工作起來其實是沒有假日的,工作遭遇的問題,會在假日試圖解決,因此,也就沒有時間寫文章了,所以偷懶一下。大家也可以輕鬆看。在上幾回中,我們或是直接用 JDBC,或是用 JPA, MyBatis (如果讀者沒有看過前幾回,又不了解 JDBC, JPA, MyBatis,建議先閱讀前幾回再回到這裡,當然,如果讀者天資聰穎,才貌雙全 /* 應該與 “貌” 無關!*/,也是可以直接閱讀這一回), 在這裡我們並舉對照加以比較,這三種作法,是對資料庫的編碼不同,主要差別在 Respository (Dao), 我們就比對這個檔案,其他的檔案,在這裡就忽略不看,如果大家想知道細節,可以翻回去看。
只討論兩個函式,一個是findAll(), 一個是 userAdd(), 如果直接使用 JDBC
private JdbcTemplate jdbcTemplate;
public void userAdd(User user) {
String sql_format= ("insert into users(name,email) value(?,?)";
jdbcTemplate.update(sql_format,user.getName(),user.getEmail());
}
public List<User> findAll() {
String sql= "select id,name,email from users";
return jdbcTemplate.query(sql, (rs, rowNum) -> new User(rs.getString("name"),rs.getString("email")));
}
控制得最仔細,欄位的對應是 "手動" 的,findAll() 也可以寫成
public List<User> findAll() {
String sql=String.format("select id,name,email from %s", USERS);
List<User> users = jdbcTemplate.query(sql, new UserRowMapper());
return users;
}
而 RowMapper 是獨立的類別,適合欄位較多的狀況。
public class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(new Integer(rs.getInt("id")));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
接著我們看一下JPA/Hibernate
public interface IUserRepository extends JpaRepository<User,Long> {
List<User> findAll();
}
繼承自 JpaRepository,findAll() 函式一行搞定,沒有 SQL,沒有欄位對應,一切就成了,但是 userAdd() 不見了,使用時改用 save(),使用方法相同 (當然,把 save() 再外裹一層,變成 userAdd() 也是合法的)。這就是成衣的概念,拿起來就可以穿,但是有些東西是事先依模子作好的,口袋有幾個,位置在何處…。到了 MyBatis,似乎介於兩個中間。
@Update("INSERT INTO USERS(name,email) VALUES(#{user.name}, #{user.email})")
void userAdd(@Param("user") User user);
@Select("SELECT * FROM users")
List<User> findAll();
需要 SQL 指令,但是不需要處理欄位對應關係(其實是己經寫入SQL指令之中)。不管是 Hibernate 或是 MyBatis 編寫的都是界面 (Interface), 只有函式的宣告,而不需要定義函式執行的邏輯,至於JDBC則是類別(class)。欄位的對應關係 JPA/Hibernate是寫在模型(Model)(JDBC 是手動對照, MyBatis 若是資料庫欄位名稱與類別相同則不必定義,若不相同,請參考上一回),就如例中 User 類別:
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name="ID")
private long id;
@Column(name="NAME")
private String name;
@Column(name="EMAIL")
private String email;
若是如範例,資料庫欄位名稱與類別名稱相同,@Column一行亦可省略。
處理資料庫是應用程式不可或缺的一塊,工具的特點就是方便,模組化的特色是穩藏內部細節(使用者不必知道SQL語法)透過 Spring Boot 可以輕輕鬆鬆完成許多以往必須花費許多精神完成的事,然而,工具的日新月異,而且歧路亡羊,在精進的路上,就要深思慎選,為學要如金字塔,要能博大要能高。